﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Common;
using Model;
using PositionServer.Service;

namespace PositionServer
{
    public partial class PositionMainForm : Form
    {

        // private ServiceHost _host;
        private ThreadServiceHost _threadServiceHost;

        public static readonly Hashtable TaxiList = Hashtable.Synchronized(new Hashtable());
        public static readonly Hashtable AcceptServrtIpList = Hashtable.Synchronized(new Hashtable());        
        public static readonly Hashtable SmsList = Hashtable.Synchronized(new Hashtable());

        public static readonly Hashtable PassengerList = Hashtable.Synchronized(new Hashtable());
        public static readonly Hashtable DestinationList = Hashtable.Synchronized(new Hashtable());

        private bool _isReadSms = true;  // Thread flag
        public static bool IsUseSmsModel;


        private Thread _tUpdateTaxiOnline;//车辆在线时间计数线程 
        private Thread _tClearPrivateCar;//清除不在线的司机车线程
        private Thread _tBackDbToAccess;
        private Thread _tClearPassenger;
        private Thread _tClearTaxiList;

        private Thread _tLoadDestinationThread;


        private const string StrVersion = "当前版本号：1.0.1_bata";

        public PositionMainForm()
        {
            InitializeComponent();
            label_version1.Text = label_version2.Text = StrVersion;

            //Initialize the serial port selection box
            comboBox_Com.DropDownStyle = ComboBoxStyle.DropDownList;
            comboBox_Com.Items.Clear();
            comboBox_Com.Items.Add("不使用短信平台");
            foreach (string s in SerialPort.GetPortNames())
            {
                comboBox_Com.Items.Add(s);
            }
            comboBox_Com.SelectedIndex = 0;
          
        }

        #region SMSModel
        [DllImport("SMSDLL.dll", CharSet = CharSet.Ansi)]
        public static extern int SMSStartService(int nPort, int BaudRate, int Parity, int DataBits, int StopBits, int FlowControl, string csca);

        [DllImport("SMSDLL.dll", CharSet = CharSet.Ansi)]
        public static extern int SMSStopSerice();

        [DllImport("SMSDLL.dll", CharSet = CharSet.Ansi)]
        public static extern int SMSSendMessage(string Msg, string PhoneNo);

        [DllImport("SMSDLL.dll", CharSet = CharSet.Ansi)]
        public static extern int SMSQuery(int index);


        [DllImport("SMSDLL.dll", CharSet = CharSet.Ansi)]
        public static extern bool SMSSeviceStarted();


        [DllImport("SMSDLL.dll", CharSet = CharSet.Ansi)]
        public static extern int SMSGetNextMessage(ref  SMSMessageStruct Msg);
        public struct SMSMessageStruct
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public byte[] Msg;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public byte[] PhoneNo;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public byte[] ReceTime;
        }

        #endregion

        private void MainForm_Load(object sender, EventArgs e)
        {
            InitServerOperation();
            #region For Test
            ////!--For Test
            //Random r = new Random();
            //for (int i = 0; i < 100; i++)
            //{

            //    int rr = r.Next(1, 1000);

            //    int rr2 = r.Next(1, 1000);

            //    TaxiInfo taxiInfo = new TaxiInfo
            //                                  {
            //                                      Id = i,
            //                                      DriverPhoneNumber = i.ToString().PadLeft(12, '0'),
            //                                      Longitude = 114.40 + rr / 1000f,
            //                                      Latitude = 30.47 + rr2 / 1000f,
            //                                      TaxiState = (byte)(i % 3),
            //                                      Ip = IPAddress.Parse("192.168.1.1"),
            //                                      TaxiType = "红色世嘉" + i,
            //                                      TaxiNo = "鄂A0" + i.ToString().PadLeft(4, '0'),
            //                                      UpdateTime = DateTime.Now,
            //                                      DriverName = i.ToString(),
            //                                      Remark = "光通信科技",
            //                                      AlarmL = 0,


            //                                  };
            //    TaxiList.Add(i.ToString(), taxiInfo);
            //}
            //// _isClearCache = true;
            //Thread t = new Thread(UpdateGps);
            //t.Start();
            #endregion
        }

        private void UpdateGps()
        {
            Int64 iii = 0;
            while (true)
            {
                Thread.Sleep(5000);
                Random r = new Random();

                foreach (TaxiInfo taxi in TaxiList.Values)
                {
                    double rr = r.NextDouble() / 1000;
                    double rr2 = r.NextDouble() / 1000;
                    if (iii % 2 == 0)
                    {
                        taxi.Latitude += rr;
                        taxi.Longitude += rr2;
                    }
                    else
                    {
                        taxi.Latitude -= rr;
                        taxi.Longitude -= rr2;
                    }
                    taxi.UpdateTime = DateTime.Now;
                }
                iii++;

            }

        }


        /// <summary>
        ///!--1 Get  And  Load  DataBase Config and Server Config
        /// </summary>
        private void InitServerOperation()
        {
            ConfigInfo config = OperateConfig.GetPosServerConfig();
            string isAutoStart = config.AutoStart;
            textBox_datBaseName.Text = config.DatBaseName;
            textBox_serverName.Text = config.ServerName;
            textBox_userName.Text = config.UserId;
            textBox_passWord.Text = config.PassWord;
            comboBox_Com.Text = config.Com;
            AutocheckBox.Checked = isAutoStart == "1";
            if (isAutoStart == "1")
            {
                StartService();
            }
            else
            {
                InitControlAfterStopService();
            }
        }


 

        private void btnStartSerer_Click(object sender, EventArgs e)
        {
            StartService();
        }

        /// <summary>
        ///!--4 return 1 means succeed ,return 0 means false
        /// </summary>
        public bool CheckDataBasesConnection()
        {
            if (BLL.SysManage.CheckDb(textBox_datBaseName.Text) == 0)
            {
                MessageBox.Show(@"系统数据库连接失败！请检查配置。");
                return false;
            }
            return true;
        }


        private bool InitSmsCom()
        {
            if (comboBox_Com.Text == "不使用短信平台")
            {
                IsUseSmsModel = false;
            }
            else
            {
                IsUseSmsModel = true;
                try
                {
                    int port = int.Parse(comboBox_Com.Text.Remove(0, 3));
                    if (SMSStartService(port, 9600, 2, 8, 0, 0, "card") != 1)
                    {
                        MessageBox.Show("短信平台启动失败");
                        return false;
                    }
                }
                catch (Exception ex)
                {
                    CommonRoutine.HandlingExceptions(ex);
                    return false;
                }

            }
            return true;
        }


        /// <summary>
        /// !--3 Start WCF Service
        /// </summary>
        private void StartService()
        {
            InitControlAfterStartService();
            //Get is AutoStart
            string autoStart = AutocheckBox.Checked ? "1" : "0";
            string comstr = comboBox_Com.Text;
            OperateConfig.SavePosServerConfig(autoStart, comstr);
            if (!CheckDataBasesConnection())
            {
                InitControlAfterStopService();
                return;
            }
            if (!InitSmsCom())
            {
                InitControlAfterStopService();
                return;
            }



            try
            {
                _threadServiceHost = new ThreadServiceHost();
                _threadServiceHost.Start();
                //Thread t = new Thread(TaxiClearCache);
                //t.Start();
                //_isReadSms = true;
                //Thread t2 = new Thread(ReadSms);
                //t2.Start();

                _tUpdateTaxiOnline = new Thread(UpdateTaxiOnlineTimeByDay);
                _tUpdateTaxiOnline.IsBackground = true;
                _tUpdateTaxiOnline.Start();


                //_tClearPrivateCar = new Thread(ClearUnconnectedPrivateCar);
                //_tClearPrivateCar.IsBackground = true;
                //_tClearPrivateCar.Start();
                _tBackDbToAccess = new Thread(BackUpToAccess);
                _tBackDbToAccess.IsBackground = true;
                _tBackDbToAccess.Start();


                _tClearPassenger = new Thread(ClearPassenger);
                _tClearPassenger.IsBackground = true;
                _tClearPassenger.Start();

                _tLoadDestinationThread = new Thread(LoadDestinationsInThread);
                _tLoadDestinationThread.IsBackground = true;
                _tLoadDestinationThread.Start();


                _tClearTaxiList = new Thread(ClearTaxiList);
                _tClearTaxiList.IsBackground = true;
                _tClearTaxiList.Start();

            }
            catch (Exception ex)
            {
                CommonRoutine.HandlingExceptions(ex, true);
                OperateConfig.SavePosServerConfig("0", comstr);
                System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().Location);
                Environment.Exit(0);
            }


        }


        private void InitControlAfterStartService()
        {
            // Init Control
            spState.Text = @" 监控服务已启动 ...";
            btnStartSerer.Enabled = false;
            btnStopServer.Enabled = true;
            comboBox_Com.Enabled = false;
            AutocheckBox.Enabled = false;
            SetServer.Enabled = false;
            label_version2.Enabled = true;

            _isReadSms = true;
        }


        private void ReadSms()
        {
            while (_isReadSms && IsUseSmsModel)
            {
                SMSMessageStruct stu = new SMSMessageStruct();
                int smsCount = SMSGetNextMessage(ref stu);
                if (smsCount != 0)
                {
                    string phoneNo = Encoding.GetEncoding("GBK").GetString(stu.PhoneNo).Trim('\0');
                    string receDateTime = Encoding.GetEncoding("GBK").GetString(stu.ReceTime).Trim('\0');
                    string content = Encoding.GetEncoding("GBK").GetString(stu.Msg).Trim('\0');
                    ArrayList al = new ArrayList { phoneNo, receDateTime, content };
                    SmsList[phoneNo] = al;
                }
                Thread.Sleep(3000);
            }
        }

        private void btnStopServer_Click(object sender, EventArgs e)
        {
            try
            {
                ClearTaxiOnlineTime(true);
                _tUpdateTaxiOnline.Abort();
                //_tClearPrivateCar.Abort();

                AcceptServrtIpList.Clear();
                TaxiList.Clear();
                InitControlAfterStopService();
                if (_threadServiceHost != null)
                {
                    _threadServiceHost.Stop();
                }
                if (IsUseSmsModel)
                {
                    _isReadSms = false;
                }
            }
            catch (Exception ex)
            {
                CommonRoutine.HandlingExceptions(ex);
            }

        }

        private void InitControlAfterStopService()
        {
            //set control state
            btnStartSerer.Enabled = true;
            btnStopServer.Enabled = false;
            comboBox_Com.Enabled = true;
            AutocheckBox.Enabled = true;
            SetServer.Enabled = true;
            _isReadSms = false;
            spState.Text = @" 监控服务已停止 ...";
        }

        private void HideServer_Click(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
            ShowInTaskbar = false;
            Visible = false;
        }

        private void button_TestConnection_Click(object sender, EventArgs e)
        {
            ConfigInfo config = new ConfigInfo
                                          {
                                              AutoStart = AutocheckBox.Checked ? "1" : "0",
                                              DatBaseName = textBox_datBaseName.Text,
                                              ServerName = textBox_serverName.Text,
                                              UserId = textBox_userName.Text,
                                              PassWord = textBox_passWord.Text
                                          };
            OperateConfig.SavePosServerConfig(config);
            if (CheckDataBasesConnection())
            {
                BLL.SysManage.UpdataConnectstring();
                MessageBox.Show(@"数据库连接成功！");

            }
        }



        private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                WindowState = FormWindowState.Normal;
                ShowInTaskbar = true;
                Visible = true;
                Focus();
            }
            else
            {
                WindowState = FormWindowState.Minimized;
                ShowInTaskbar = false;
                Visible = false;
            }
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show("是否确定关闭位置服务器？", "警告：", MessageBoxButtons.OKCancel)
            == DialogResult.Cancel)
            {
                e.Cancel = true;
                return;
            }
           
            _isReadSms = false;
            notifyIcon1.Visible = false;

            this.Visible = false;         
            ClearTaxiOnlineTime(true);

            Environment.Exit(0);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            string showtext = TaxiList.Count.ToString();
            PositionService p = new PositionService();
            System.Data.DataSet ds = p.TaxiGpsHistoryGetListWhere(
                "DriverPhoneNumber ='" + "13627264054'");
            int rowCouont = ds.Tables[0].Rows.Count;

            #region 对GPS信息进行分段统计
            //List<RouteInfo> roteList = new List<RouteInfo>();
            //double distance = 0;
            //DateTime startTime = new DateTime();
            //DateTime endTime = new DateTime();
            //double startLat = 0;
            //double startLng = 0;
            //double endLat = 0;
            //double endLng = 0;
            //int taxistate = -1;
            //DateTime dtStart = DateTime.Now;
            //for (int i = 0; i < rowCouont; i++)
            //{
            //    System.Data.DataRow row = ds.Tables[0].Rows[i];
            //    int state = int.Parse(row["TaxiState"].ToString());
            //    double lng = double.Parse(row["Longitude"].ToString());
            //    double lat = double.Parse(row["Latitude"].ToString());
            //    string time = row["Updatetime"].ToString();

            //    if (taxistate == -1)
            //    {
            //        taxistate = state;
            //        startLat = lat;
            //        startLng = lng;
            //        endLat = lat;
            //        endLng = lng;
            //        startTime = DateTime.Parse(time);
            //    }
            //    else
            //    {
            //        if (taxistate == state)
            //        {
            //            distance += CommonRoutine.GetDistanceBetweenTwoGps(
            //              lat, lng, endLat, endLng);
            //            endLat = lat;
            //            endLng = lng;
            //            endTime = DateTime.Parse(time);

            //            if (i == rowCouont - 1)
            //            {
            //                RouteInfo model = new RouteInfo();
            //                model.state = taxistate;
            //                model.phone = "13627264054";
            //                model.startLat = startLat;
            //                model.startLng = startLng;
            //                model.startTime = startTime;
            //                model.endLat = endLat;
            //                model.endLng = endLng;
            //                model.endTime = endTime;
            //                model.distance = distance;

            //                roteList.Add(model);
            //            }

            //        }
            //        else
            //        {
            //            RouteInfo model = new RouteInfo();
            //            model.state = taxistate;
            //            model.phone = "13627264054";
            //            model.startLat = startLat;
            //            model.startLng = startLng;
            //            model.startTime = startTime;
            //            model.endLat = endLat;
            //            model.endLng = endLng;
            //            model.endTime = endTime;
            //            model.distance = distance;

            //            roteList.Add(model);

            //            distance = 0;
            //            taxistate = state;
            //            startLat = lat;
            //            startLng = lng;
            //            endLat = lat;
            //            endLng = lng;
            //            startTime = DateTime.Parse(time);
            //        }
            //    }

            //}
            //TimeSpan span = DateTime.Now - dtStart;

            //int si = 0;
            //foreach (RouteInfo routeInfo in roteList)
            //{
            //    TaxiRouteHistoryInfo model = new TaxiRouteHistoryInfo();
            //    model.PhoneNumber = "13627264054";
            //    model.StartTime = routeInfo.startTime;
            //    model.EndTime = routeInfo.endTime;
            //    model.StartLat = routeInfo.startLat;
            //    model.StartLng = routeInfo.startLng;
            //    model.EndLat = routeInfo.endLat;
            //    model.EndLng = routeInfo.endLng;
            //    model.Distance = routeInfo.distance;
            //    model.State = routeInfo.state;
            //    if (p.TaxiRouteHistoryAdd(model))
            //    {
            //        si++;
            //    }
            //}

            #endregion


            //TaxiGpsHistoryInfo model = new TaxiGpsHistoryInfo();
            //model.Time=DateTime.Parse("2013-5-5 00:00:00");
            //model.Latitude = 30.478898;
            //model.Longitude = 114.403115;
            //model.Taxistate = 0x00;
            //model.DriverPhoneNumber = "13627264054";
            ////int state=0;
            //int count = 0;
            //int sum = 0;
            //PositionService p = new PositionService();
            //int i = 0;
            //do
            //{
            //    Random ran = new Random();
            //    model.Longitude = model.Longitude + ran.Next(-9, 9)*0.000001;
            //    model.Latitude = model.Latitude + ran.Next(-9, 9)*0.000001;
            //    if (count==sum)
            //    {
            //        sum = 0;
            //        if (model.Taxistate==0x00)
            //        {
            //            model.Taxistate = 0x01;
            //            count = ran.Next(10 * 5, 10 * 60);
                        
            //        }
            //        else
            //        {
            //            model.Taxistate = 0x00;
            //            count = ran.Next(3, 10 * 6);
            //        }
            //    }
            //    sum++;
            //    i++;
            //    p.AddTaxiGpsHistoryInfo(model);                
            //    model.Time = model.Time.AddSeconds(10);
            //} while (model.Time<DateTime.Now);
            
                //AcceptServrtIpList.Count.ToString();

            //lock (AcceptServrtIpList.SyncRoot)
            //{
            //    foreach (DictionaryEntry dictionaryEntry in AcceptServrtIpList)
            //    {
            //        ArrayList al = ((ArrayList)dictionaryEntry.Value);
            //        showtext = showtext + "接入服务器IP：" + dictionaryEntry.Key +"___"+ al.Count + Environment.NewLine;
            //        //foreach (string phoneNum in al)
            //        //{
            //        //    showtext = showtext + phoneNum + ",";
            //        //}
            //        showtext += Environment.NewLine;
            //    }
            //}
            MessageBox.Show(showtext);
        }
      

        private void ClearTaxiOnlineTime(bool isToday)
        {            
            PositionService positonService = new PositionService();
            positonService.ClearTaxiOnlineTime(isToday);
        }

       
        private void UpdateTaxiOnlineTimeByDay()
        {
            while (true)
            {
                string nextday = DateTime.Now.Date.AddDays(1).ToString("yyyy-MM-dd")
                    + " 00:00:00";
                TimeSpan span = DateTime.Parse(nextday) - DateTime.Now;
                int sleepSeconds = (int)span.TotalSeconds + 10;
                Thread.Sleep(sleepSeconds * 1000);    
                ClearTaxiOnlineTime(false);
               
            }             
        }

        /// <summary>
        /// 每天凌晨清除一次未在线的私家车
        /// </summary>
        private void ClearUnconnectedPrivateCar()
        {
            DateTime nextDay = DateTime.Parse(DateTime.Now.AddDays(1).Date.ToString());
            TimeSpan span = nextDay - DateTime.Now;
            Thread.Sleep((int)span.TotalSeconds * 1000);            
            while (true)
            {
                List<string> delkeys = new List<string>();
                lock (TaxiList.SyncRoot)
                {
                    foreach (TaxiInfo taxi in TaxiList.Values)
                    {
                        //私家车十分钟内未更新 
                        if (taxi.CarType==ConstParameters.CarTypeOfPrivate
                            && ((DateTime.Now-taxi.UpdateTime).Minutes>10))
                        {
                            delkeys.Add(taxi.DriverPhoneNumber);
                        }
                    }
                }
                foreach (string delkey in delkeys)
                {
                    TaxiList.Remove(delkey);
                }
                Thread.Sleep(24*60*60*1000);
            }             
        }

        public void BackUpToAccess()
        { 
            DateTime nextDay = DateTime.Parse(DateTime.Now.AddDays(1).Date.ToString());
            TimeSpan span = nextDay - DateTime.Now;            
            Thread.Sleep((int)span.TotalSeconds * 1000+100*1000);
            while (true)
            {
                string path = "D:\\TaxiServer_Excel";
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                path += "\\" + DateTime.Today.AddDays(-1).ToString("yyyy_MM_dd");
                path += ".mdb";
                if (!File.Exists(path))
                {
                    //从debug文件夹下复制源文件
                    string source = Environment.CurrentDirectory + "\\Temp.mdb";
                    if (!File.Exists(source))
                    {
                        return;
                    }
                    File.Copy(source, path);
                }
                PositionService positionService = new PositionService();
                positionService.BackUpDbFromMySqlToAccess(path);
                Thread.Sleep(24 * 60 * 60 * 1000);
            }                         
        }


        /// <summary>
        /// 每天凌晨清除一次未在线的私家车
        /// </summary>
        private void ClearPassenger()
        {
            DateTime nextDay = DateTime.Parse(DateTime.Now.AddDays(1).Date.ToString());
            TimeSpan span = nextDay - DateTime.Now;
            Thread.Sleep((int)span.TotalSeconds * 1000);
            while (true)
            {
                List<string> delkeys = new List<string>();
                lock (PassengerList.SyncRoot)
                {
                    foreach (PassengerInfo psg in PassengerList.Values)
                    {                        
                        if ((DateTime.Now-psg.UpdateTime).Minutes>120)
                        {
                            delkeys.Add(psg.PhoneNumber);
                            if (!string.IsNullOrEmpty(psg.CarPhoneNumber))
                            {
                                TaxiInfo taxi = TaxiList[psg.CarPhoneNumber]
                                                as TaxiInfo;
                                if (taxi!=null)
                                {
                                    taxi.PassengerPhoneNumber = "";
                                }
                            }
                        }
                    }
                }
                foreach (string delkey in delkeys)
                {
                    PassengerList.Remove(delkey);                     
                }
                Thread.Sleep(24 * 60 * 60 * 1000);
            }
        }

        private void LoadDestinationsInThread()
        {
            PositionService positionService = new PositionService();
            List<DestinationInfo> list = positionService.DestinationToList();
            lock (DestinationList.SyncRoot)
            {
                DestinationList.Clear();
                foreach (DestinationInfo destinationInfo in list)
                {
                    DestinationList[destinationInfo.Id] = destinationInfo;
                }
            }

            DateTime nextDay = DateTime.Parse(DateTime.Now.AddDays(1).Date.ToString());
            TimeSpan span = nextDay - DateTime.Now;
            Thread.Sleep((int)span.TotalSeconds * 1000);
            while (true)
            {
                list.Clear();
                list = positionService.DestinationToList();
                lock (DestinationList.SyncRoot)
                {
                    DestinationList.Clear();
                    foreach (DestinationInfo destinationInfo in list)
                    {
                        DestinationList[destinationInfo.Id] = destinationInfo;
                    }
                }
                Thread.Sleep(24 * 60 * 60 * 1000);
            }
        }

        private void ClearTaxiList()
        {
            while (true)
            {
                Thread.Sleep(180 * 1000);
                DateTime now = DateTime.Now;
                ArrayList delKey = new ArrayList();
                try
                {
                    lock (TaxiList.SyncRoot)
                    {
                        foreach (DictionaryEntry dictionaryEntry in TaxiList)
                        {
                            TaxiInfo taxi = (TaxiInfo) dictionaryEntry.Value;
                            TimeSpan timeSpan = new TimeSpan(now.Ticks - taxi.UpdateTime.Ticks);
                            if (timeSpan.TotalSeconds > 360)
                            {
                                delKey.Add(dictionaryEntry.Key);
                                Console.WriteLine("车辆连接时间超时，从内存中清除：号码" + taxi.DriverPhoneNumber);
                            }
                        }
                    }

                    foreach (string phoneNumber in delKey)
                    {

                        TaxiList.Remove(phoneNumber);

                    }
                }
                catch (Exception ex)
                {
                    CommonRoutine.HandlingExceptions(ex);
                    LogService.WriteLog("PositionMainForm.cs  TaxiListClear");
                }
            }

        }


      
         
    }
}
